//
// Created by Administrator on 2025-06-19.
//

#include "ByteStreamPool.h"

ByteStreamPool::ByteStreamPool(size_t blockSize)
        : blockSize_(blockSize) {}

ByteStreamPool::~ByteStreamPool()
{
    for(auto &block: blocks_)
    {
        std::free(block.data);
    }
}

void *ByteStreamPool::alloc(size_t size)
{
    // 1. 优先复用
    for(auto it = freeList_.begin(); it != freeList_.end(); ++it)
    {
        if (it->second >= size)
        {
            void *ptr = it->first;
            freeList_.erase(it);
            return ptr;
        }
    }

    // 2. 当前块尝试分配
    if (!blocks_.empty())
    {
        Block &block = blocks_.back();
        if (block.capacity - block.used >= size)
        {
            void *ptr = block.data + block.used;
            block.used += size;
            return ptr;
        }
    }

    // 3. 分配新块
    allocateBlock(size);
    Block &newBlock = blocks_.back();
    void *ptr = newBlock.data + newBlock.used;
    newBlock.used += size;
    return ptr;
}

void ByteStreamPool::free(void *ptr, size_t size)
{
    // 简单放入 freeList 等待复用
    freeList_.emplace_back(ptr, size);
}

void ByteStreamPool::allocateBlock(size_t minSize)
{
    size_t size = blockSize_;
    if (size < minSize) size = minSize * 2;
    uint8_t *data = static_cast<uint8_t *>(std::malloc(size));
    if (!data) throw std::bad_alloc();
    blocks_.push_back(Block{data, size, 0});
}
